//Grupo 6 turma A
//Decisões de Projeto

//As palavras terão apenas letras.
//Frases serão delimitadas por pontos de gramática ou /n
//separadores de palavra utilizados: " ,.;<>:/?^~]}[{'`=+-_)(*&$#@!\n\t\r\\"
//separadores de frase utilizados: ".;!?)(][}{\n\t\r"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>

#define NTHREADS 8

void strToUpper(char *);
int checaPalindromo(char *);
void removeEspacos (char *);

int main(void)
{
	//declaração de variaveis
	int contPalavra = 0, contFrase = 0, i = 0;
	char bufferFrase[400], bufferPalavra[400], bufferAux[400];

	omp_set_num_threads(NTHREADS);

	FILE *ifp;
    ifp = fopen("shakespe.txt", "rb");

	while(!feof(ifp))
	{

		fgets(bufferPalavra, 400, ifp);

		strcpy(bufferFrase, bufferPalavra);

		char* aux1;

		char* aux2;


        #pragma omp sections
        {
            //Aqui as sections são usadas para paralelizar os palindromos referentes as palavras
            #pragma omp section
            {
                char* tokens1 = strtok(bufferPalavra, " ,.;<>:/?^~]}[{'`=+-_)(*&$#@!\n\t\r\\");

                while(tokens1 != NULL)
                {

                    aux1 = strdup(tokens1);

                    //checa se é palindromo
                    if (checaPalindromo(aux1))
                    {
                        #pragma omp critical
                        contPalavra++;
                    }

                    tokens1 = strtok(NULL, " ,./?'\";|^-!$#@`~*&%)(+=_}{][\n\t\r\\");
                }

            }

            //Aqui as sections são usadas para paralelizar os palindromos referentes as frases
            #pragma omp section
            {
                //strtok divide a frase em varias palavras
                char* tokens2 = strtok(bufferFrase, ".;!?)(][}{\n\t\r");
                while(tokens2 != NULL)
                {

                    aux2 = strdup(tokens2);
                    removeEspacos(aux2);

                    //checa se eh palindromo
                    if (checaPalindromo(aux2))
                    {
                        #pragma omp critical
                        contFrase++;

                    }

                    tokens2 = strtok(NULL, ".?;!()[]{}\n\t\r");

                }


            }

        }

	}

	printf("Total de frases palindromo: %d\n", contFrase);
	printf("Total de palavras palindromo: %d\n",contPalavra);

	fclose(ifp);
	return 0;

}


//Passa a palavra para letras maiúsculas
void strToUpper(char *str)
{

	int i = 0;

	for (i = 0 ; i <= strlen(str) - 1 ; i++)
	{
		str[i] = toupper(str[i]);
	}
}

//Remove todos espaços em branco para tratar a frase, transformando ela em uma unica palavra
void removeEspacos(char * str)
{
    int i = 0;
    char *src = str;

    char *dst = src;

    while (*src != '\0')
	{
        if (*src != ' ')
		{
            *dst++ = *src;
		}
		else if(*src == ' ')
		{
            i++;
		}

        src++;
    }

    *dst = '\0';
}

//Se a frase invertida for igual a frase original, então é palindromo
int checaPalindromo(char *str)
{
    char *pt1, *pt2;

	char aux1[400];

	if(strlen(str) > 1)
	{
		strToUpper(str);
		strcpy(aux1,str);

		////
		//faz swap da palavra
        for (pt1 = str, pt2 = str + strlen(str) - 1; pt1 < pt2; --pt2, ++pt1)
        {

            *pt1 ^= *pt2;
            *pt2 ^= *pt1;
            *pt1 ^= *pt2;
        }
        ////

		if(strcmp(str, aux1) == 0)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
	else
	{

		return 0;
	}
}
